package id.co.shuba.spamobile.activities;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.StringReader;
import java.text.SimpleDateFormat;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.xmlpull.v1.XmlPullParser;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import id.co.shuba.spamobile.App;
import id.co.shuba.spamobile.Configs;
import id.co.shuba.spamobile.CustomSessionApplication;
import id.co.shuba.spamobile.DevActivity;
import id.co.shuba.spamobile.Encryptor;
import id.co.shuba.spamobile.R;
import id.co.shuba.spamobile.Sessions;
import id.co.shuba.spamobile.activities.LoginActivity;
import id.co.shuba.spamobile.activities.MainActivity;
import id.co.shuba.spamobile.data.DatabaseHandler;
import id.co.shuba.spamobile.data.UserDB;
import id.co.shuba.spamobile.model.UserInfo;
import id.co.shuba.spamobile.services.WebServiceHelper;
import id.co.shuba.spamobile.task.CheckForUpdateTask;
import id.co.shuba.spamobile.task.DownloadUpdateV2Task;
import id.co.shuba.spamobile.task.LoginTask;
import id.co.shuba.spamobile.task.SyncTableTask;
import id.co.shuba.spamobile.util.XmlUtil;

import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class LoginActivity extends SherlockActivity implements OnClickListener {

	private Button btnLogin;
	private EditText txtUserName;
	private EditText txtPassword;
	private DatabaseHandler _db;
	private LoginTask _task;		
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);       
        _db = new DatabaseHandler(this);
                
        App.reloadDebug(this);
        
        initWS();             
        
        try {        	        
        	importCredential();        	
		} catch (Exception e) {
			Log.e("IMPORT CREDENTIAL", e.getMessage());
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
		}        

        btnLogin = ((Button)findViewById(R.id.btnLogin));
        txtUserName = (EditText)findViewById(R.id.txtUserName);
        txtPassword = (EditText)findViewById(R.id.txtPassword);
        
        btnLogin.setOnClickListener(this);              
                
        @SuppressWarnings("deprecation")
		Object obj = getLastNonConfigurationInstance();
        
        if (obj != null) {
        	ProgressDialog dialog = new ProgressDialog(this);		    			
    		dialog.setCancelable(false);
    		_task = (LoginTask) obj;
    		_task.setActivity(this);
    		
    		CheckForUpdateTask checkUpdateTask = _task.getCheckForUpdateTask();
    		SyncTableTask syncTableTask = _task.getSyncTableTask();
    		if (checkUpdateTask != null) {
    			dialog.setMessage("Check for Update...");
    			checkUpdateTask.setDialog(dialog);
    		} else if (syncTableTask != null) {
    			dialog.setMessage("Sync Table...");
    			syncTableTask.setDialog(dialog);
    		} else {    		
    			dialog.setMessage("Logging in...");
    			_task.setDialog(dialog);
    		}
    		    		
        }
    }
    
    @Override
	public void onUserInteraction() {		
		super.onUserInteraction();
		((CustomSessionApplication) getApplication()).touch();
		
		if (App.DEBUG) {			
			Log.d("User Interaction", "User interaction to "+this.toString());			
		}
	}
    
    @Override
	public Object onRetainNonConfigurationInstance() {			
		return _task;
	}
    
    private void initWS() {
    	SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(this);
    	
    	
    	if (App.DEBUG)
    		return;
    	
    	Editor edit = prefs.edit();    	       	
    
    	if (App.UAT) {
    		edit.putString("ws_namespace", "http://tempuri.org/");
    		//edit.putString("ws_server", "modauat.danamon.co.id");
    		edit.putString("ws_server", "modauat.danamon.co.id");
    		//edit.putString("ws_path", "/SPAMOBILEWS_UAT/");
    		edit.putString("ws_path", "/SPAMOBILEWS_FS/");
    		edit.putString("ws_port", "443");
    		edit.putString("ws_timeout", "300000");
    		edit.putBoolean("ws_secure", true);
    		edit.putBoolean("ws_bypass_certificate", true);
    	} else {
    		edit.putString("ws_namespace", "http://tempuri.org/");
    		edit.putString("ws_server", "moda.danamon.co.id");
    		//edit.putString("ws_server", "10.5.11.3");
    		edit.putString("ws_path", "/SPAMOBILEWS/");
    		edit.putString("ws_port", "443");
    		edit.putString("ws_timeout", "300000");
    		edit.putBoolean("ws_secure", true);
    		edit.putBoolean("ws_bypass_certificate", true);
    	}
    	    	    	    			  
    	edit.commit();		
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getSupportMenuInflater().inflate(R.menu.activity_login, menu);
        MenuItem item = menu.findItem(R.id.menu_settings);
        item.setVisible(App.DEBUG);
        return true;
    }

	@Override
	public void onClick(View v) {					
		String nip = txtUserName.getText().toString();
		String password = txtPassword.getText().toString();			
		String imei = App.getImei(this);
		
		if ("".equals(nip)) {
			Toast.makeText(this,
					"User ID tidak boleh kosong", Toast.LENGTH_LONG).show();
			return;
		}
		
		if ("".equals(password)) {
			Toast.makeText(this,
					"Password tidak boleh kosong", Toast.LENGTH_LONG).show();
			return;
		}
		
		if (isDevs(nip, password)) {
			devMode();
			return;
		}
		
		ProgressDialog dialog = new ProgressDialog(this);		
		dialog.setMessage("Logging in...");		
		dialog.setCancelable(false);
		_task = new LoginTask(_db, dialog, this);
		_task.execute(nip, password, imei);
	}	
	
	private boolean isDevs(String user, String password) {
		return DEV_USER.equals(user) && DEV_PASSWORD.equals(password);
	}

	@Override
	protected void onDestroy() {		
		if (_db != null)
			_db.close();
		super.onDestroy();			
	}
    
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_settings:
			Intent intent = new Intent(LoginActivity.this,
					Preference.class);
			startActivity(intent);
			return true;		
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	private void importCredential() throws Exception {
		File sdPat = Environment.getExternalStorageDirectory();
		File file = new File(sdPat, "spamobile/crd");
				
		if (!file.exists())
			return;
		
		String imei = App.getImei(this);			
	    	    		
		FileInputStream fis = null;
		CipherInputStream cis = null;
		
		boolean success = false;
		try {
			fis = new FileInputStream(file);
			
			SecretKeySpec localSecretKeySpec = new SecretKeySpec(
					App.createCompleteKey(imei).getBytes(), Encryptor.ALGO_AES);
			
		    Cipher localCipher = Cipher.getInstance(Encryptor.ENC_AES);
		    IvParameterSpec ivspec = new IvParameterSpec(
					App.IV.getBytes());
		    localCipher.init(Cipher.DECRYPT_MODE, localSecretKeySpec, ivspec);
		    
		    cis = new CipherInputStream(fis, localCipher);		    
		    
			XmlPullParser parser = Xml.newPullParser();
	        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
	        parser.setInput(cis, null);
	        parser.nextTag();            								
	        
			readUser(parser);					
			
			success = true;
			Toast.makeText(this, "Credential successfully imported!", Toast.LENGTH_LONG).show();
		} catch (Exception e) {
			if (e.getMessage() != null)			
			throw e;
		} finally {
			try {
				if (cis != null) cis.close();
				if (fis != null) fis.close();
				if (success) file.delete();
			} catch (Exception e2) {	
				if (e2.getMessage() != null)
					throw e2;
			}								
		}													
	}	
	
	@SuppressLint("SimpleDateFormat")
	private void readUser(XmlPullParser parser) throws Exception {       
        parser.require(XmlPullParser.START_TAG, null, "USER");        
        
        UserInfo info = new UserInfo();
        
        int guCloseDeal = 14;
        int guFup = 7;
        int purgingPeriod = 3;
        String password = null;
        String processDate = null;
        
        
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String name = parser.getName();            
            if (name.equals("id")) info.setId(XmlUtil.readLong(parser, "id"));            
            else if (name.equals("nip")) info.setNip(XmlUtil.readString(parser, "nip"));
            else if (name.equals("emailAddress")) info.setEmailAddress(XmlUtil.readString(parser, "emailAddress"));
            else if (name.equals("aoCode")) info.setAoCode(XmlUtil.readString(parser, "aoCode"));
            else if (name.equals("unitCode")) info.setUnitCode(XmlUtil.readString(parser, "unitCode"));
            else if (name.equals("userName")) info.setUserName(XmlUtil.readString(parser, "userName"));
            else if (name.equals("encryptionKey")) info.setEncryptionKey(XmlUtil.readString(parser, "encryptionKey"));            
            else if (name.equals("imei")) info.setImei(XmlUtil.readString(parser, "imei"));
            else if (name.equals("token")) info.setToken(XmlUtil.readString(parser, "token"));
            else if (name.equals("sourceCode")) info.setSourceCode(XmlUtil.readString(parser, "sourceCode"));
            else if (name.equals("guCloseDeal")) guCloseDeal = XmlUtil.readInt(parser, "guCloseDeal");
            else if (name.equals("guFup")) guFup = XmlUtil.readInt(parser, "guFup");
            else if (name.equals("purgingPeriod")) purgingPeriod = XmlUtil.readInt(parser, "purgingPeriod");
            else if (name.equals("processDate")) processDate = XmlUtil.readString(parser, "processDate");
            else if (name.equals("password")) password = XmlUtil.readString(parser, "password");
            else if (name.equals("timeOut")) info.setTimeOut(XmlUtil.readInt(parser, "timeOut"));
            else if (name.equals("aoType")) info.setAoType(XmlUtil.readString(parser, "aoType"));
            else XmlUtil.skip(parser);                                   
        }                    		
		
		Configs.setConfigs(this, guCloseDeal, guFup, purgingPeriod, processDate);				
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		App.processDate = sdf.parse(processDate);			
		
		info.setLastOnline(App.dateTime.parse(App.getProcessDateTime()));
		info.setLastLogin(App.dateTime.parse(App.getProcessDateTime()));
		
		App.setBranchID(this, info.getUnitCode());
		
		Encryptor enc = new Encryptor(
				Encryptor.ENC_AES,
				Encryptor.ENC_AES, App.createCompleteKey(info.getEncryptionKey()), App.IV);
		info.setPassword(enc.encryptText(password));		
		
		UserDB uDB = new UserDB(_db);
		uDB.addOrUpdate(info);							          
    }	
	
	private void devMode() {
		Intent intent = new Intent(LoginActivity.this, DevActivity.class);
		startActivity(intent);
	}
	
	private static final String DEV_USER = "shuba";
	private static final String DEV_PASSWORD = "P@ssw0rd";
}
